/**
 * 交叉类型
 */

interface DogInterface {
    run() : void
}

interface CatInterface {
    jump(): void
}

let pet: DogInterface & CatInterface = {
    run() {},
    jump() {}
}

class Dog implements DogInterface {
    run() {}
    eat() {}
}

class Cat implements CatInterface {
    jump() {}
    eat() {}
}

enum Master { Boy, Girl }
function getPet(master: Master) {
    let pet = master === Master.Boy ? new Dog() : new Cat()
    pet.eat()
    // Property 'run' does not exist on type 'Dog | Cat'.
    // Property 'run' does not exist on type 'Cat'.
    // pet.run()
    return pet
}

/**
 * 以下，通过 `kind` 这个公共属性，实现…… 不同的保护区块
 */

interface Square {
    kind: "square"
    size: number
}
interface Rectangle {
    kind: "rectangle"
    width: number
    height: number
}
interface Circle {
    kind: 'circle'
    r: number
}
type Shape = Square | Rectangle | Circle
function area(s: Shape) : number {
    switch (s.kind) {
        case "square":
            return s.size * s.size
        case "rectangle":
            return s.height * s.width
        case "circle":
            return Math.PI * s.r ** 2
        default:
            // Argument of type 'Circle' is not assignable to parameter of type 'never'.
            return ((e: never) => {throw new Error(e)})(s)
    }
}

console.log(area({kind: 'circle', r: 1}))

